﻿using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using XYS.Core.Models;
using XYS.Core.Util.Helper;

namespace XYS.Service.Core
{
    /// <summary>
    /// jwt相关配置
    /// </summary>
    public static class JWTExtension
    {
        /// <summary>
        /// 自定义 jwt 事件
        /// </summary>
        private static JwtBearerEvents JwtBearerEvents { get; set; }

        /// <summary>
        /// 添加 自定义 jwt 事件
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="jwtBearerEvents"></param>
        /// <returns></returns>
        public static WebApplicationBuilder AddJwtBearerEvents(this WebApplicationBuilder builder, JwtBearerEvents jwtBearerEvents)
        {
            JwtBearerEvents = jwtBearerEvents;
            return builder;
        }

        /// <summary>
        /// 添加jwt配置
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="loggerFactory"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static WebApplicationBuilder AddJWTSetting(this WebApplicationBuilder builder, ILoggerFactory loggerFactory)
        {
            var logger = loggerFactory.CreateLogger("AddJWTSetting");
            //获取 JWT配置
            TokenHelper.Lssuer = builder.Configuration["JWT_Issuer"];
            if (TokenHelper.Lssuer == null) return builder;

            if (!TokenHelper.Lssuer.EndsWith("_" + GlobalCoreSetting.EnvironmentName))
                TokenHelper.Lssuer += "_" + GlobalCoreSetting.EnvironmentName;

            TokenHelper.SecurityKey = builder.Configuration["JWT_SecretKey"];
            TokenHelper.Audience = builder.Configuration["JWT_Audience"];

            //Token 有效期
            if (TimeSpan.TryParse(builder.Configuration["JWT_InvalidTime"], out var invalidTime))
                TokenHelper.InvalidTime = invalidTime;

            //续签有效期
            if (TimeSpan.TryParse(builder.Configuration["RenewalToken_InvalidTime"], out var renewalTokenInvalidTime))
                TokenHelper.RenewalTokenInvalidTime = renewalTokenInvalidTime;

            logger.LogInformation("Token InvalidTime：{InvalidTime}", TokenHelper.InvalidTime);

            if (TokenHelper.Secret == null)
            {
                var error = "JWT配置有误，请增加配置JWT_Issuer、JWT_SecretKey、JWT_Audience";
                logger.Log(LogLevel.Error, error);
                throw new Exception(error);
            }


            // 注册服务
            builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters()
                {
                    NameClaimType = ClaimTypes.Name,
                    IssuerSigningKey = new SymmetricSecurityKey(TokenHelper.Secret), //SecurityKey
                    ClockSkew = TimeSpan.FromSeconds(10), //过期时间容错值，解决服务器端时间不同步问题（秒）
                    ValidateLifetime = true,
                    //颁发机构
                    ValidIssuer = TokenHelper.Lssuer,
                    //受众
                    ValidAudience = TokenHelper.Audience,
                };
                options.Events = new JwtBearerEvents
                {
                    OnAuthenticationFailed = context =>
                    {
                        return JwtBearerEvents?.OnAuthenticationFailed?.Invoke(context) ?? Task.CompletedTask;
                    },
                    OnTokenValidated = context =>
                    {
                        return JwtBearerEvents?.OnTokenValidated?.Invoke(context) ?? Task.CompletedTask;
                    },
                    OnMessageReceived = context =>
                    {
                        return JwtBearerEvents?.OnMessageReceived?.Invoke(context) ?? Task.CompletedTask;
                    },
                    OnChallenge = context =>
                    {
                        return JwtBearerEvents?.OnChallenge?.Invoke(context) ?? Task.CompletedTask;
                    },
                    OnForbidden = context =>
                    {
                        return JwtBearerEvents?.OnForbidden?.Invoke(context) ?? Task.CompletedTask;
                    },
                };
            });

            return builder;
        }


    }
}

